package com.example.qbbcrssreader;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.util.Xml;


public class BBCXmlParser {

    // Parse the BBC RSS feed using the XmlPullParser class, without using namespaces.
    public List<Entry> parse(InputStream in) throws XmlPullParserException, IOException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(in, null);
            return readFeed(parser);
        } finally {
            in.close();
        }
    }

    // The XML data is parsed into the 'entries' array, with it's members being immutable after the
    // instantiation of an 'Entry'. The 'entries' array is then sorted into date order. 
    private List<Entry> readFeed(XmlPullParser parser) throws XmlPullParserException, IOException {
        List<Entry> entries = new ArrayList<Entry>();

        String title = null;
        String description = null;
        String link = null;
        Date pubDate = null;
    	SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
        List<String> media = new ArrayList<String>();
        boolean channelEndTag = false;
        boolean itemActive = false;
        int eventType = parser.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT && !channelEndTag) {
        	String name = null;
        	switch (eventType) {
        		case XmlPullParser.START_DOCUMENT:
        			break;
        		case XmlPullParser.START_TAG:
        			name = parser.getName();
        			if (name.equals("item")) {
        				title = null;
        				description = null;
        				link = null;
        				pubDate = null;
        				media.clear();
        				itemActive = true;
        			} else if (name != null && itemActive ){
        				if (name.equals("title")) {
        					title = parser.nextText();
        				} else if (name.equals("description")) {
        					description = parser.nextText();
        				} else if (name.equals("link")) {
        					link = parser.nextText();
        				} else if (name.equals("pubDate")) {
        	            	try {
        						pubDate = formatter.parse(parser.nextText());
        					} catch (ParseException e) {
        						e.printStackTrace();
        					}
        				} else if (name.equals("media:thumbnail")) {
        					media.add(parser.getAttributeValue(null, "url"));
        				}
        			}
        			break;
        		case XmlPullParser.END_TAG:
        			name = parser.getName();
        			if (name.equals("item")) {
        				// Avoid an NPE when there are no thumbnail URLs, otherwise just get the first one.
        				String mediaThumbnail = (media.isEmpty())? null: media.get(0);
        				// Check that we're inserting a sane 'Entry'.
        				if (title != null && description != null && link != null && pubDate != null) {
        					entries.add(new Entry(title,description,link,pubDate,mediaThumbnail));
        				}
        				itemActive = false;
        			} else if (name.equals("channel")) {
        				channelEndTag = true;
        			}
        			break;
        	}
        	eventType = parser.next();
        }
        // Sort the entries into descending publication date/time order
        Collections.sort((List<Entry>)entries, new Comparator<Entry>() {
            public int compare(Entry a, Entry b) {
                return b.pubDate.compareTo( a.pubDate );
            }
        });
        return entries;
    }

    // This class represents a single entry (post) in the XML feed.
    public static class Entry {
        public final String title;
        public final String description;
        public final String link;
        public final Date pubDate;
        public final String mediaThumbnail;

        // An 'Entry' is immutable after instantiation.
        private Entry(String title, String description, String link, Date pubDate, String mediaThumbnail) {
            this.title = title;
            this.description = description;
            this.link = link;
            this.pubDate = pubDate;
            this.mediaThumbnail = mediaThumbnail;
        }
    }
}
